home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / OGRID110 / TCHASH.PAS < prev    next >
Pascal/Delphi Source File  |  1995-06-01  |  7KB  |  262 lines

  1.  
  2. { Copyright (c) 1989,90 by Borland International, Inc. }
  3.  
  4. unit TCHash;
  5. { Turbo Pascal 6.0 object-oriented example hash tables.
  6.   This unit is used by TCALC.PAS.
  7.   See TCALC.DOC for an more information about this example.
  8. }
  9.  
  10. {$S-}
  11.  
  12. interface
  13.  
  14. uses TCUtil;
  15.  
  16. { This unit allows you to implement hash tables.  Each hash table is composed
  17.   of a number of "buckets", each of which points to a linked list of data
  18.   entries.  The bucket that a particular data entry goes into is determined
  19.   by the HashValue function. }
  20.  
  21. const
  22.   MaxBuckets = 1000;
  23.   MaxHashItemSize = 256;
  24.  
  25. type
  26.   BucketRange = 1..MaxBuckets;
  27.   HashItemSizeRange = 1..MaxHashItemSize;
  28.   HashItemData = array[0..Pred(MaxHashItemSize)] of Byte;
  29.   HashItemDataPtr = ^HashItemData;
  30.   HashItemPtr = ^HashItem;
  31.   HashItem = record
  32.     Next : HashItemPtr;
  33.     Data : HashItemData;
  34.   end;
  35.   HashItemArray = array[BucketRange] of HashItemPtr;
  36.   HashTable = object
  37.     Buckets : BucketRange;
  38.     Items : Longint;
  39.     CurrItem : HashItemPtr;
  40.     CurrBucket : BucketRange;
  41.     HashData : ^HashItemArray;
  42.     constructor Init(InitBuckets : BucketRange);
  43.     destructor Done;
  44.     function Add : Boolean;
  45.     procedure Delete(Deleted : Pointer);
  46.     function FirstItem : HashItemPtr;
  47.     function NextItem : HashItemPtr;
  48.     function Change : Boolean;
  49.     function Search : HashItemPtr;
  50.     function HashValue : LongInt; virtual;
  51.     function Found(Item : HashItemPtr) : Boolean; virtual;
  52.     procedure CreateItem(var Item : HashItemPtr); virtual;
  53.     function ItemSize : HashItemSizeRange; virtual;
  54.     function CurrItemSize(Item : HashItemPtr) : HashItemSizeRange; virtual;
  55.   end;
  56.  
  57. implementation
  58.  
  59. constructor HashTable.Init(InitBuckets : BucketRange);
  60. { Initialize a new hash table with a certain number of buckets }
  61. begin
  62.   GetMem(HashData, InitBuckets * SizeOf(HashItemPtr));
  63.   if HashData = nil then
  64.     Fail;
  65.   Buckets := InitBuckets;
  66.   FillChar(HashData^, Buckets * SizeOf(HashItemPtr), 0);
  67.   Items := 0;
  68. end; { HashTable.Init }
  69.  
  70. destructor HashTable.Done;
  71. { Removes a hash table from memory }
  72. var
  73.   P, D : HashItemPtr;
  74.   Counter : Word;
  75. begin
  76.   for Counter := 1 to Buckets do
  77.   begin
  78.     P := HashData^[Counter];
  79.     while P <> nil do
  80.     begin
  81.       D := P;
  82.       P := P^.Next;
  83.       FreeMem(D, CurrItemSize(D) + SizeOf(HashItemPtr));
  84.     end;
  85.   end;
  86.   FreeMem(HashData, Buckets * SizeOf(HashItemPtr));
  87. end; { HashTable.Done }
  88.  
  89. function HashTable.Add : Boolean;
  90. { Adds a new item to a hash table }
  91. var
  92.   H, A : HashItemPtr;
  93.   V : BucketRange;
  94. begin
  95.   Add := False;
  96.   V := Succ(HashValue mod Buckets);
  97.   H := HashData^[V];
  98.   A := H;
  99.   while H <> nil do
  100.   begin
  101.     H := H^.Next;
  102.     if H <> nil then
  103.       A := H;
  104.   end;
  105.   if A = nil then    { Item will be the first element in the list }
  106.   begin
  107.     GetMem(HashData^[V], ItemSize + SizeOf(HashItemPtr));
  108.     A := HashData^[V];
  109.     if A = nil then
  110.       Exit;
  111.   end
  112.   else begin         { Add item and end of list }
  113.     GetMem(A^.Next, ItemSize + SizeOf(HashItemPtr));
  114.     if A^.Next = nil then
  115.       Exit;
  116.     A := A^.Next;
  117.   end;
  118.   CreateItem(A);
  119.   A^.Next := nil;
  120.   Inc(Items);
  121.   Add := True;
  122. end; { HashTable.Add }
  123.  
  124. procedure HashTable.Delete(Deleted : Pointer);
  125. { Deletes an item from a hash table, and returns the deleted item }
  126. var
  127.   H, D : HashItemPtr;
  128.   V : BucketRange;
  129. begin
  130.   V := Succ(HashValue mod Buckets);
  131.   H := HashData^[V];
  132.   D := H;
  133.   while (H <> nil) and (not Found(H)) do
  134.   begin
  135.     H := H^.Next;
  136.     if not Found(H) then
  137.       D := H;
  138.   end;
  139.   if H = nil then        { The item was not found }
  140.   begin
  141.     if Deleted <> nil then
  142.       FillChar(Deleted^, ItemSize, 0);
  143.     Exit;
  144.   end
  145.   else begin
  146.     if H = HashData^[V] then
  147.       HashData^[V] := HashData^[V]^.Next
  148.     else
  149.       D^.Next := H^.Next;
  150.     if Deleted <> nil then   { Fill Deleted with the item's data }
  151.       Move(H^.Data, Deleted^, ItemSize);
  152.     FreeMem(H, CurrItemSize(H) + SizeOf(HashItemPtr));
  153.   end;
  154.   Dec(Items);
  155. end; { HashTable.Delete }
  156.  
  157. function HashTable.FirstItem : HashItemPtr;
  158. { Returns the first item in a hash table.  to find all of the items in a
  159.   hash table, call FirstItem to get the first one and then call NextItem to
  160.   get the rest }
  161. var
  162.   Counter : Word;
  163. begin
  164.   for Counter := 1 to Buckets do
  165.   begin
  166.     CurrBucket := Counter;
  167.     CurrItem := HashData^[Counter];
  168.     if CurrItem <> nil then
  169.     begin
  170.       FirstItem := CurrItem;
  171.       Exit;
  172.     end;
  173.   end;
  174.   FirstItem := nil;
  175. end; { HashTable.FirstItem }
  176.  
  177. function HashTable.NextItem : HashItemPtr;
  178. { Returns the next item in a hash table - called after FirstItem }
  179. begin
  180.   CurrItem := CurrItem^.Next;
  181.   if CurrItem <> nil then
  182.   begin
  183.     NextItem := CurrItem;
  184.     Exit;
  185.   end;
  186.   while CurrBucket < Buckets do
  187.   begin
  188.     Inc(CurrBucket);
  189.     CurrItem := HashData^[CurrBucket];
  190.     if CurrItem <> nil then
  191.     begin
  192.       NextItem := CurrItem;
  193.       Exit;
  194.     end;
  195.   end;
  196.   NextItem := nil;
  197. end; { HashTable.NextItem }
  198.  
  199. function HashTable.Change : Boolean;
  200. { Changes the data of a hash item }
  201. var
  202.   H : HashItemPtr;
  203. begin
  204.   H := HashData^[Succ(HashValue mod Buckets)];
  205.   while (H <> nil) and (not Found(H)) do
  206.     H := H^.Next;
  207.   if H <> nil then
  208.   begin
  209.     CreateItem(H);
  210.     Change := True;
  211.   end
  212.   else
  213.     Change := Add;
  214. end; { HashTable.Change }
  215.  
  216. function HashTable.Search : HashItemPtr;
  217. { Searches for a particular hash item }
  218. var
  219.   H : HashItemPtr;
  220. begin
  221.   H := HashData^[Succ(HashValue mod Buckets)];
  222.   while (H <> nil) and (not Found(H)) do
  223.     H := H^.Next;
  224.   Search := H;
  225. end; { HashTable.Search }
  226.  
  227. function HashTable.HashValue : LongInt;
  228. { Returns a hash value - must be written by the user }
  229. begin
  230.   Abstract('HashTable.HashValue');
  231. end; { HashTable.HashValue }
  232.  
  233. function HashTable.Found(Item : HashItemPtr) : Boolean;
  234. { Returns a boolean value indicating whether the current hash item is the
  235.   one being searched for - must be written by the user }
  236. begin
  237.   Abstract('HashTable.Found');
  238. end; { HashTable.Found }
  239.  
  240. procedure HashTable.CreateItem(var Item : HashItemPtr);
  241. { Creates a hash item - must be written by the user }
  242. begin
  243.   Abstract('HashTable.CreateItem');
  244. end; { HashTable.CreateItem }
  245.  
  246. function HashTable.ItemSize : HashItemSizeRange;
  247. { Returns the size of a hash item.  If the hash item size is variable, this
  248.   is based on whatever the item being searched for, added, or deleted is - 
  249.   must be written by the user }
  250. begin
  251.   Abstract('HashTable.ItemSize');
  252. end; { HashTable.ItemSize }
  253.  
  254. function HashTable.CurrItemSize(Item : HashItemPtr) : HashItemSizeRange;
  255. { Returns the size of a particular item.  This needs to be written only if
  256.   the size of hash items is variable (strings, etc.) }
  257. begin
  258.   CurrItemSize := ItemSize;
  259. end; { HashTable.CurrItemSize }
  260.  
  261. end.
  262.